package archivos;

import graphs.AMatrixGraph;
import graphs.GraphADT;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import utils.OS;

/**
 * @file Sif.java
 * @author Juan Humanes Ferrer
 * @date 04-Marzo-2014
 * @description Clase para tratar con ficheros .sif
 */
public class Sif {

    /**
     * Método que recibe como parámetro un fichero .sif y a partir de ese
     * fichero crea un grafo
     *
     * @param archivo
     * @return grafo
     */
    public static GraphADT leeSIF(File archivo) {

        List<String[]> listaGeneral = new ArrayList();
        List<String> listaVertices = new ArrayList();

        FileReader fr = null;
        BufferedReader br = null;

        GraphADT grafo = new AMatrixGraph();

        try {
            // Apertura del fichero y creacion de BufferedReader para poder
            // hacer una lectura comoda (disponer del metodo readLine()).

            fr = new FileReader(archivo);
            br = new BufferedReader(fr);

            // Lectura del fichero
            String linea;
            while ((linea = br.readLine()) != null) {
                String[] org = linea.split(" ");
                if (listaVertices.contains(org[0]) == false) {
                    listaVertices.add(org[0]);
                }
                listaGeneral.add(org);
            }

            int tam = listaVertices.size();
            boolean[][] matrizAristas = new boolean[tam][tam];

            for (int i = 0; i < tam; i++) {
                for (int j = 0; j < tam; j++) {
                    matrizAristas[i][j] = false;
                }
            }

            for (String[] genes : listaGeneral) {
                String orgCentral = genes[0];
                int posCentral = listaVertices.indexOf(orgCentral);

                if (genes.length > 1) {
                    if (posCentral != -1) {
                        for (int j = 2; j < genes.length; j++) { //Empezamos en 2 ya que la posicion 1 es la segunda columna -> type relation

                            String organismoSel = genes[j];
                            int posSel = listaVertices.indexOf(organismoSel);

                            if (posSel != -1) {
                                matrizAristas[posCentral][posSel] = true;
                            } else {
                            }

                        }
                    } else {
                    }
                }
            }

            //Si hasta aqui todo va bien, se crea el grafo           
            grafo.setVertices(listaVertices.toArray());

            grafo.setAMtrix(matrizAristas);

            grafo.setNumVertices(tam);

        } catch (IOException e) {

        } finally {
            // En el finally cerramos el fichero, para asegurarnos
            // que se cierra tanto si todo va bien como si salta 
            // una excepcion.
            try {
                if (null != fr) {
                    fr.close();
                }
            } catch (IOException e2) {
            }
        }
        return grafo;
    }

    /**
     * Método que a partir de un grafo crea un archivo .sif en la ubicacion
     * indicada
     *
     * @param grafo
     * @param ubicacion2
     * @param titulo
     * @throws IOException
     */
    public static void crearArchivoSif(GraphADT grafo, String ubicacion2, String titulo) throws IOException {
        try {

            if (grafo != null) {

                String separator = OS.getDirectorySeparator();

                FileWriter ficheroSIF = null;
                PrintWriter pwSIF = null;

                ficheroSIF = new FileWriter(ubicacion2 + separator + titulo + ".sif");
                pwSIF = new PrintWriter(ficheroSIF);

                boolean[][] adjMatrix = grafo.getAdjMatrix();
                List<String> listaVertices = grafo.getVertices();

                //Se recorre la matriz para saber cual es el ultimo enlace
                List enlaces = new ArrayList();

                for (int i = 0; i < listaVertices.size(); i++) {
                    boolean enl = false;
                    for (int j = 0; j < i; j++) {
                        if (i != j) {
                            if (adjMatrix[i][j] == true) {
                                enl = true;
                            }
                        }
                    }
                    if (enl) {
                        enlaces.add("si");
                    } else {
                        enlaces.add("no");
                    }

                }

                for (int i = 0; i < listaVertices.size(); i++) {
                    if (i != 0) {
                        pwSIF.flush();
                        pwSIF.println();
                        pwSIF.flush();
                    }
                    pwSIF.flush();
                    if (enlaces.get(i).equals("si")) {
                        pwSIF.print(listaVertices.get(i) + " relation ");
                    } else {
                        pwSIF.print(listaVertices.get(i));
                    }

                    pwSIF.flush();
                    for (int j = 0; j < i; j++) {

                        if (i != j) {

                            if (adjMatrix[i][j] == true) {
                                pwSIF.flush();
                                pwSIF.print(listaVertices.get(j) + " ");
                                pwSIF.flush();
                            }
                        }
                    }

                    pwSIF.flush();
                }
                pwSIF.flush();
                ficheroSIF.close();
                pwSIF.close();

            } else {
            }
        } catch (IOException e) {
        }
    }

    public static void crearArchivoSifOut(GraphADT grafo, Writer out) throws IOException {
        try {

            if (grafo != null) {

                boolean[][] adjMatrix = grafo.getAdjMatrix();
                List<String> listaVertices = grafo.getVertices();

                //Se recorre la matriz para saber cual es el ultimo enlace
                List enlaces = new ArrayList();

                for (int i = 0; i < listaVertices.size(); i++) {
                    boolean enl = false;
                    for (int j = 0; j < i; j++) {
                        if (i != j) {
                            if (adjMatrix[i][j] == true) {
                                enl = true;
                            }
                        }
                    }
                    if (enl) {
                        enlaces.add("si");
                    } else {
                        enlaces.add("no");
                    }

                }

                for (int i = 0; i < listaVertices.size(); i++) {
                    if (i != 0) {
                        out.flush();
                        out.append("\n");
                        out.flush();
                    }
                    out.flush();
                    if (enlaces.get(i).equals("si")) {
                        out.append(listaVertices.get(i) + " relation ");
                    } else {
                        out.append(listaVertices.get(i));
                    }

                    out.flush();
                    for (int j = 0; j < i; j++) {

                        if (i != j) {

                            if (adjMatrix[i][j] == true) {
                                out.flush();
                                out.append(listaVertices.get(j) + " ");
                                out.flush();
                            }
                        }
                    }

                    out.flush();
                }
                out.flush();

            } else {
            }
        } catch (IOException e) {
        }
    }
}
